package com.zyl.Ecs.collector.task;

import com.zyl.Ecs.collector.client.RealTimeClient;
import com.zyl.Ecs.collector.mapper.SensorMapper;
import com.zyl.Ecs.common.domain.data.bean.DataBean;
import com.zyl.Ecs.common.domain.device.bean.Sensor;
import com.zyl.Ecs.common.response.Result;
import com.zyl.Ecs.common.response.ResultCode;
import com.zyl.Ecs.common.utils.CUtil;
import com.zyl.Ecs.common.utils.ObjectUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.stream.Collectors;

/**
 * @version v1.0
 * @ProjectName: Ecs
 * @Package: com.zyl.Ecs.collector.task
 * @ClassName: DataUploadRunner
 * @Description TODO 数据上传启动任务
 * @Author 翟玉龙
 * @Date 2024/12/6-14:36
 */
@Component
@RequiredArgsConstructor
public class DataUploadRunner implements ApplicationRunner {

    private final SensorMapper sensorMapper;
    private final RealTimeClient realtimeClient;

    private List<Sensor> sensors;

    @Override
    public void run(ApplicationArguments args) {
        long uploadPeriod = 5000;
        long flushPeriod = 20000;
        /* 启动数据上传任务 */
        Timer timer = new Timer();
        timer.schedule(new DataUploadTask(), 0, uploadPeriod);
        /* 启动传感器数据刷新任务，每60秒刷新一次传感器信息 */
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                updateSensors();
            }}, 0, flushPeriod);
    }

    private synchronized void updateSensors() {
        sensors = listSensors();
    }

    private synchronized List<Sensor> getSensors() {
        return sensors;
    }

    private List<Sensor> listSensors() {
        return sensorMapper.selectList(null);
    }

    private static void threadSleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            CUtil.logError(e.getMessage());
        }
    }

    class DataUploadTask extends TimerTask {

        @Override
        public void run() {
            long currentTimeMillis = System.currentTimeMillis() / 1000 * 1000;
            try {
                runTask(listSensors(), currentTimeMillis);
            } catch (Exception e) {
                CUtil.logInfo(
                        String.format(
                                "[collector]采集器上传数据失败，%s",
                                e.getMessage()
                        )
                );
            }
        }

        /**
         * 根据传感器类型生成传感器数据
         *
         * @param sensors 传感器列表
         * @param time    数据采集时间
         * @throws Exception 异常
         */
        private void runTask(List<Sensor> sensors, long time) throws Exception {
            /* 生成数据采集时间，精确到秒 */
            Result<?> resultVO = realtimeClient.upload(sensors.stream()
                    .map(sensor -> DataBean.builder()
                            .value(generateValue(sensor.getSensorTypeId()))
                            .time(time)
                            .sensorId(sensor.getId())
                            .build())
                    .collect(Collectors.toList()));
            if (ObjectUtil.notEquals(resultVO.getCode(), ResultCode.SUCCESS.getCode())) {
                CUtil.logError(
                        String.format(
                                "[Collector] 上传数据失败，信息：%s",
                                resultVO.getMessage()
                        )
                );
            }
        }

        /**
         * 根据传感器类型生成传感器数据
         * @param sensorTypeId 传感器类型
         * @return {@link Double }
         */
        private Double generateValue(Integer sensorTypeId) {
            switch (sensorTypeId) {
                case 1:
                    return Math.random() * 5 + 16D;
                case 2:
                    return Math.random() * 4 + 28D;
                case 3:
                    return Math.random() * 4 + -20D;
                case 4:
                    return (int) (Math.random() * 3) - 1D;
                default:
                    return 0D;
            }
        }
    }
}
